/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
    constructor(exector) {
      try {
        exector(this.resolve,this.reject)
      }catch(e) {
        this.reject(e)
      }
    }
    status = PENDING
    successCallback = []
    failCallback = []
    value = undefined
    reason = undefined
    resolve = (value) => {
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.value = value
        
        while(this.successCallback.length) { // 处理当前promsie 循环注册回调问题 
            this.successCallback.shift()()
        }
    }
    reject = (reason) => {
        if(this.status !== PENDING) return
        this.status = REJECTED
        this.reason = reason
        while(this.failCallback.length) {  // 处理当前promsie 循环注册回调问题 
          this.failCallback.shift()()
        }
    }
    then(successCallback,failCallback) {
      successCallback = successCallback ? successCallback : value => value; // 解决then() 无参数情况 
      failCallback = failCallback ? failCallback : reason => { throw reason };
     let promise2 = new MyPromise((resolve,reject) => { //解决promise的串联问题
        if(this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = successCallback(this.value)
            resolvePromise(promise2,x,resolve, reject) //处理then的返回值的类型
          } catch(e) { // 回调代码可能出错
             reject(e)
          }
        }, 0);
        }else if(this.status  === REJECTED){
          setTimeout(() => {
            try {
              let x = failCallback(this.reason)
              resolvePromise(promise2,x,resolve, reject) //处理then的返回值的类型
            } catch(e) { // 回调代码可能出错
               reject(e)
            }
          }, 0);
        }else { // 考虑到异步的情况，加入队列
            this.successCallback.push(() => { // 必须为箭头函数，处理this为undefind的问题
                 setTimeout(() => {
                    try {
                      let x = successCallback(this.value)
                      resolvePromise(promise2,x,resolve, reject) //处理then的返回值的类型
                    } catch(e) { // 回调代码可能出错
                       reject(e)
                    }
                  }, 0);
            }) 
            this.failCallback.push(()  => {
                setTimeout(() => {
                    try {
                      let x = failCallback(this.reason)
                      resolvePromise(promise2,x,resolve, reject) //处理then的返回值的类型
                    } catch(e) { // 回调代码可能出错
                       reject(e)
                    }
                  }, 0);
            })
        }  
     })
     return promise2
    }
    catch(failCallback){
        return this.then(undefined, failCallback)
    }
    static reolve(value) {
        if(value instanceof MyPromise) return value
        return new MyPromise(value => reslove(value))
    }
    static finally(callback) {
      return this.then(value => {
        return MyPromise.reslove(callback()).then(()=> value)
      }, reason => {
        return MyPromise.reolve(callback).then(() => {throw reason})
      })
    }
    static all(array) {
      let result = []
      let index = 0
      return new MyPromise((resolve,rejected)=>{
           function addData(key,value) {
               result[key] = value
               index++
               if(index === array.length) {
                   resolve(result)
               }
           }
          for(let i = 0 ;i<array.length;i++) {
              let current = array[i]
              if(current instanceof MyPromise){
                // promise object
               current.then(value => addData(i,value),reason => rejected(reason))
              }else {
               //normal value
               addData(i,array[i])
           }
          }
      })
  }
}
function resolvePromise(promise,p,resolve,reject) {
    if(promise === p) {
       return reject(new TypeError(`你错了`)) // 处理循环返回当前promise
    }                                      
    if(p instanceof MyPromise) {  // p为 promise 根据他的返回值的状态 来调用 resolve或reject
        p.then(resolve,reject)
    }else {
        resolve(p)
    }
}